# Copyright (c) 2019 Presto Labs Pte. Ltd.
# Author: xguo

import datetime
import functools
from coin.exchange.base.kr_rest.derivative_util import (get_last_friday, get_last_month_of_quarter)

from coin.exchange.kraken.kr_rest.currency import KrakenCurrency
from coin.exchange.kraken.kr_rest.constants import quote_currency_list

from coin.exchange.base.kr_rest.futures_product import (PERPETUAL_DATE)
from coin.exchange.kraken_futures.kr_rest.native_private_client import (KrakenFuturesProductCode)

EXPIRY_TIME = datetime.time(hour=8)


def convert_to_exact_kraken_futures_expiry(expiry):
  if expiry == PERPETUAL_DATE:
    return expiry
  else:
    return datetime.datetime.combine(expiry.date(), EXPIRY_TIME)


@functools.lru_cache(maxsize=256)
def parse_kraken_futures_currency_pair(currency_pair, current_datetime):
  currency_pair = currency_pair.upper()
  for quote_str in quote_currency_list:
    quote = KrakenCurrency.FromStr(quote_str, current_datetime)
    if currency_pair.endswith(quote.native_currency):
      base_str = currency_pair[:-len(quote.native_currency)]
      base = KrakenCurrency.FromStr(base_str, current_datetime)
      return base, quote
  raise ValueError('Unknown currency pair %s', currency_pair)


@functools.lru_cache(maxsize=256)
def parse_kraken_futures_native_symbol(native_symbol, current_datetime):
  native_symbol = native_symbol.upper()
  splitted = native_symbol.split('_')
  assert len(splitted) in (2, 3), 'Invalid native_symbol'
  if len(splitted) == 2:
    product_code, currency_pair = splitted
    expiry = PERPETUAL_DATE
  else:
    product_code, currency_pair, expiry = splitted
    expiry = datetime.datetime.strptime(expiry, '%y%m%d')
    expiry = convert_to_exact_kraken_futures_expiry(expiry)
  product_code = product_code.upper()
  base, quote = parse_kraken_futures_currency_pair(currency_pair, current_datetime)
  parsed_result = {
      'product_code': KrakenFuturesProductCode(product_code),
      'base': base,
      'quote': quote,
      'expiry': expiry,
  }
  return parsed_result


def expiry_str_to_datetime(expiry_str, current_datetime):
  if expiry_str == 'PERPETUAL':
    expiry = PERPETUAL_DATE
  elif expiry_str == 'MONTH':
    month = current_datetime.month
    expiry = get_last_friday(current_datetime.year, month)
  elif expiry_str == 'QUARTER':
    month = get_last_month_of_quarter(current_datetime)
    expiry = get_last_friday(current_datetime.year, month)
  else:
    expiry = datetime.datetime.strptime(expiry_str, '%Y%m%d')
  return convert_to_exact_kraken_futures_expiry(expiry)


def guess_kraken_futures_product_code(quote, expiry):
  if expiry == PERPETUAL_DATE:
    if quote.currency == 'USD':
      product_code = KrakenFuturesProductCode.PERPETUAL_INVERSE_FUTURES
    else:
      product_code = KrakenFuturesProductCode.PERPETUAL_VANILLA_FUTURES
  else:
    if quote.currency == 'USD':
      product_code = KrakenFuturesProductCode.INVERSE_FUTURES
    else:
      product_code = KrakenFuturesProductCode.VANILLA_FUTURES
  return product_code


def form_kraken_futures_native_symbol(base, quote, expiry, product_code):
  if expiry == PERPETUAL_DATE:
    native_symbol = '%s_%s%s' % (product_code.value, base.native_currency, quote.native_currency)
  else:
    native_symbol = '%s_%s%s_%s' % (
        product_code.value, base.native_currency, quote.native_currency, expiry.strftime('%y%m%d'))
  return native_symbol
